using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using GraphAlgsPresentation.GraphEditor;
using GraphAlgsPresentation.ScriptPlayer;
using System.Diagnostics;
using System.Threading;

namespace PresentationManager
{
    /// <summary>
    /// Represents a windows form of PresentationManager
    /// </summary>
    public partial class FormPresentationManager : Form
    {
        private DemoDatabase database;
        private DemoInfo currentDemo;
        private string DatabasePath = Application.StartupPath + "\\Database.xml";
        private GraphEditor graphEditor = new GraphEditor();
        private ScriptPlayer scriptPlayer = new ScriptPlayer();
        string[] FileList =
            new string[] { "PresentationCore.dll", "ScriptBuilder.dll", "ScriptLibrary.dll" };

        /// <summary>
        /// Gets or sets the current demo.
        /// </summary>
        /// <value>The current demo.</value>
        DemoInfo CurrentDemo
        {
            get { return currentDemo; }
            set
            {
                currentDemo = value;
                if (value == null)
                    lblAlgName.Text = string.Empty;
                else
                    lblAlgName.Text = value.Name;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FormPresentationManager"/> class.
        /// </summary>
        public FormPresentationManager()
        {
            InitializeComponent();
            if (File.Exists(DatabasePath))
            {
                TextReader reader = new StreamReader(DatabasePath);
                database = DemoDatabase.Deserialize(reader);
                reader.Close();
            }
            else
            {
                database = new DemoDatabase();
                TextWriter writer = new StreamWriter(DatabasePath);
                database.Serialize(writer);
                writer.Close();
            }
            ShowControl(graphEditor);
            UpdateAlgList();
            Thread.Sleep(500);
        }

        /// <summary>
        /// Updates the alg demo list.
        /// </summary>
        private void UpdateAlgList()
        {
            this.CurrentDemo = null;
            lstAlgs.Items.Clear();
            foreach (DemoInfo info in database.DemoInformations)
                lstAlgs.Items.Add(info.Name);
            if (database.DemoInformations.Count == 0)
                return;
            lstAlgs.SelectedIndex = 0;
            this.CurrentDemo = database.DemoInformations[0];
        }

        /// <summary>
        /// Shows the control.
        /// </summary>
        /// <param name="control">The control.</param>
        private void ShowControl(UserControl control)
        {
            control.Parent = splitContainer2.Panel2;
            control.Dock = DockStyle.Fill;
            control.BringToFront();
        }

        /// <summary>
        /// Handles the Click event of the exitToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Handles the Click event of the btnShowDemoList control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnShowDemoList_Click(object sender, EventArgs e)
        {
            this.btnShowDemoList.Checked = !this.btnShowDemoList.Checked;
            this.splitContainer2.Panel1Collapsed = !this.splitContainer2.Panel1Collapsed;
            this.demonstrationListToolStripMenuItem.Checked = !this.demonstrationListToolStripMenuItem.Checked;
        }

        /// <summary>
        /// Handles the Click event of the btnGenerate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnGenerate_Click(object sender, EventArgs e)
        {
            if (this.CurrentDemo == null)
            {
                MessageBox.Show("No algorithm selected.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            this.graphEditor.Save(Application.StartupPath + @"\Graph.xml");
            File.Delete(Application.StartupPath + @"\Script.xml");
            Process genPrg = new Process();
            genPrg.StartInfo.UseShellExecute = false;
            genPrg.StartInfo.CreateNoWindow = true;
            genPrg.StartInfo.FileName = Application.StartupPath + this.CurrentDemo.Path;
            genPrg.StartInfo.Arguments = "Graph.xml Script.xml";
            genPrg.StartInfo.WorkingDirectory = Application.StartupPath;            
            genPrg.Exited += new EventHandler(genPrg_Exited);
            genPrg.EnableRaisingEvents = true;
            Cursor = Cursors.WaitCursor;
            genPrg.Start();
            genPrg.WaitForExit();
        }

        delegate void GenPrgExitDelegate();

        /// <summary>
        /// Gens the program exit.
        /// </summary>
        void GenPrgExit()
        {
            if (!File.Exists(Application.StartupPath + @"\Script.xml"))
            {
                MessageBox.Show("Script generating program error!", "Error", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            scriptPlayer.LoadScript(Application.StartupPath + @"\Script.xml");
            Cursor = Cursors.Default;
            btnShowScriptPlayer_Click(null, null);
        }

        /// <summary>
        /// Handles the Exited event of the genPrg control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void genPrg_Exited(object sender, EventArgs e)
        {
            this.Invoke(new GenPrgExitDelegate(this.GenPrgExit));
        }

        /// <summary>
        /// Handles the Click event of the btnShowGraphEditor control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnShowGraphEditor_Click(object sender, EventArgs e)
        {
            this.btnShowScriptPlayer.Checked = false;
            this.btnShowGraphEditor.Checked = true;
            this.scriptPlayerToolStripMenuItem.Checked = false;
            this.graphEditorToolStripMenuItem.Checked = true;
            ShowControl(graphEditor);
        }

        /// <summary>
        /// Handles the Click event of the btnShowScriptPlayer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnShowScriptPlayer_Click(object sender, EventArgs e)
        {
            this.btnShowScriptPlayer.Checked = true;
            this.btnShowGraphEditor.Checked = false;
            this.scriptPlayerToolStripMenuItem.Checked = true;
            this.graphEditorToolStripMenuItem.Checked = false;
            ShowControl(scriptPlayer);
        }

        /// <summary>
        /// Handles the Click event of the addToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormAlgsEditor frm = new FormAlgsEditor();
            if (frm.ShowDialog() == DialogResult.OK)
            {
                DemoInfo info = frm.DemoInfo;
                if (info.Path.StartsWith("\\"))
                    info.Path = Application.StartupPath + info.Path;

                if (!File.Exists(info.Path))
                {
                    MessageBox.Show("File not found: " + info.Path, "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                string FileName = info.Path.Substring(info.Path.LastIndexOf('\\'));
                string destPath = Application.StartupPath + "\\Demos" + FileName;

                if (!Directory.Exists(Application.StartupPath + "\\Demos"))
                    CreateDemoDirectory();

                int cnt = 1;
                string tmp = FileName;
                while (File.Exists(destPath))
                {
                    int i = tmp.LastIndexOf(".");
                    FileName = tmp.Substring(0, i) + cnt + ".exe";
                    destPath = Application.StartupPath + "\\Demos" + FileName;
                    cnt++;
                }
                File.Copy(info.Path, destPath);
                info.Path = "\\Demos" + FileName;
                database.DemoInformations.Add(info);
                TextWriter writer = new StreamWriter(DatabasePath);
                database.Serialize(writer);
                writer.Close();
                UpdateAlgList();
            }
        }

        /// <summary>
        /// Creates the demo directory.
        /// </summary>
        private static void CreateDemoDirectory()
        {
            string dir = Application.StartupPath + "\\Demos";
            Directory.CreateDirectory(dir);
            string[] FileList = 
                new string[] { "PresentationCore.dll", "ScriptBuilder.dll", "ScriptLibrary.dll" };
            foreach (string FileName in FileList)
                File.Copy(Application.StartupPath + "\\" + FileName, dir + "\\" + FileName);
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the lstAlgs control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void lstAlgs_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.CurrentDemo = database.DemoInformations[lstAlgs.SelectedIndex];
        }

        /// <summary>
        /// Handles the Click event of the demonstrationListToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void demonstrationListToolStripMenuItem_Click(object sender, EventArgs e)
        {
            btnShowDemoList_Click(null, null);
        }

        /// <summary>
        /// Handles the Click event of the graphEditorToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void graphEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            btnShowGraphEditor_Click(null, null);
        }

        /// <summary>
        /// Handles the Click event of the scriptPlayerToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void scriptPlayerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            btnShowScriptPlayer_Click(null, null);
        }

        /// <summary>
        /// Handles the Click event of the editDemonstrationToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void editDemonstrationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DemoInfo tmp = new DemoInfo();
            tmp.Path = currentDemo.Path;
            tmp.Name = currentDemo.Name;
            tmp.Description = currentDemo.Description;
            FormAlgsEditor frm = new FormAlgsEditor();
            frm.DisablePath();
            frm.DemoInfo = tmp;
            if (frm.ShowDialog() == DialogResult.OK)
            {
                database.DemoInformations[lstAlgs.SelectedIndex] = frm.DemoInfo;
                TextWriter writer = new StreamWriter(DatabasePath);
                database.Serialize(writer);
                writer.Close();
                UpdateAlgList();
            }
        }

        /// <summary>
        /// Handles the Click event of the toolStripMenuItem3 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            btnGenerate_Click(null, null);
        }

        /// <summary>
        /// Handles the Click event of the aboutToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FormAbout about = FormAbout.Instance;
            about.ShowDialog();
        }

        /// <summary>
        /// Handles the Shown event of the FormPresentationManager control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void FormPresentationManager_Shown(object sender, EventArgs e)
        {
            FormAbout.Instance.Close();
        }

        /// <summary>
        /// Handles the Click event of the deleteDemonstrationToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void deleteDemonstrationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.CurrentDemo == null) return;
            if (MessageBox.Show("Delete current algorithm?", "Graph Algorithms Presentation",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                database.DemoInformations.Remove(CurrentDemo);
                TextWriter writer = new StreamWriter(DatabasePath);
                database.Serialize(writer);
                writer.Close();
                UpdateAlgList();
            }
        }

        /// <summary>
        /// Handles the Click event of the toolStripMenuItem4 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void toolStripMenuItem4_Click(object sender, EventArgs e)
        {
            FormEffectsDemo frm = new FormEffectsDemo();
            frm.Show();
        }

        /// <summary>
        /// Handles the Click event of the helpContentsToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void helpContentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process helpProcess = new Process();
            helpProcess.StartInfo.FileName = "Help.chm";
            helpProcess.StartInfo.WorkingDirectory = Application.StartupPath;
            helpProcess.Start();
        }
    }
}